package com.azthink.chapter422.aspect;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Modifier;

@Component
@Aspect
public class HttpAspect {
    //    修饰符匹配（modifier-pattern?）
//    返回值匹配（ret-type-pattern）可以为*表示任何返回值,全路径的类名等
//    类路径匹配（declaring-type-pattern?）
//    方法名匹配（name-pattern）可以指定方法名 或者 *代表所有, set* 代表以set开头的所有方法
//    参数匹配（(param-pattern)）可以指定具体的参数类型，多个参数间用“,”隔开，各个参数也可以用“*”来表示匹配任意类型的参数，如(String)表示匹配一个String参数的方法；(*,String) 表示匹配有两个参数的方法，第一个参数可以是任意类型，而第二个参数是String类型；可以用(..)表示零个或多个任意参数
//    异常类型匹配（throws-pattern?）
//    其中后面跟着“?”的是可选项
    @Pointcut("execution(public * com.azthink.chapter422.controller.*.*(..))")
    public void cut(){}

    @Before("cut()")
    public void doBefore(JoinPoint joinPoint){
        //记录请求的url

        //RequestContextHolder，在非web控制器层获取request、response等对象
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        System.out.println("url = " + request.getRequestURI());
        //method
        System.out.println("method = "+ request.getMethod());
        //ip
        System.out.println("ip = "+request.getRemoteAddr());


        //获取切面方法的信息
        //JoinPoint对象封装了SpringAop中切面方法的信息,
        // 在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象.

        Signature signature = joinPoint.getSignature();
        System.out.println("目标方法名为:" + signature.getName());
        System.out.println("目标方法所属类的简单类名:" +  signature.getDeclaringType().getSimpleName());
        System.out.println("目标方法所属类的类名:" + signature.getDeclaringTypeName());
        System.out.println("目标方法声明类型:" + Modifier.toString(joinPoint.getSignature().getModifiers()));

        //获取传入目标方法的参数
        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            System.out.println("第" + (i+1) + "个参数为:" + args[i]);
        }


        System.out.println("执行前");
    }

    @After("cut()")
    public void doAfter(){
        System.out.println("执行后");
    }

    //在调用上面 @Pointcut标注的方法后执行。用于获取返回值
    @AfterReturning(returning = "obj", pointcut = "cut()")
    public void doAfterReturning(Object obj) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        System.out.println("response="+ objectMapper.writeValueAsString(obj));
    }


}
